﻿#pragma once
#include "uv.h"
#include "MemPool.h"

class TcpClient
{
public:
    class Listener
    {
    public:
        virtual void on_connect(TcpClient* sock, int status) {}
        virtual void on_close(TcpClient* sock) {}
        // 返回提取的数据长度
        virtual size_t on_read(TcpClient* sock, char* data, size_t dataLen) { return dataLen; }
    };

public:
	TcpClient(size_t maxBufSize = 0x10000, uv_loop_t * loop = uv_default_loop());
	virtual ~TcpClient();

    // 异步连接
    void connect(const char* host, u_short port);
    void close();
    // 异步读取
    void beginRead();
    // 异步写入
    void write(const void* data, size_t dataLen);

    int getId() { return m_id; }
    void setId(int id) { m_id = id; }
    void setListener(Listener* listener) { m_listener = listener; }

	/** 返回连接状态 */
	bool isConnected() { return uv_is_active((const uv_handle_t*)&m_handle); }

	////需要修改buf,先将数据放入buf,如果当前没发送则立即发送，否则等上次发送完接着发送，接收buf也改，使用vector<byte>，buf不够时进行扩充
	//bool send(void *data, unsigned int len);

	/** 查看数据，retLen返回已收到数据长度
	*/
	char *peek(size_t *retLen);

	/** 取出指定长度的数据，腾出缓冲区空间
	*/
	void fetch(size_t num);

protected:
    static void on_connect(uv_connect_t* req, int status);
    static void on_alloc(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
    static void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
    static void on_write(uv_write_t* req, int status);
    static void on_close(uv_handle_t* handle);

    static MemPool<uv_connect_t> s_mp_uvConnect;
    static MemPool<uv_write_t> s_mp_uvWrite;
    static MemPool<uv_buf_t> s_mp_uvBuf;

    uv_loop_t* m_loop;
    uv_tcp_t m_handle;

    int m_id = 0;
    Listener* m_listener = nullptr;

    size_t m_maxBufSize;
    char *m_recvBuf;
    //char *m_recvBuf_start;
    //char *m_recvBuf_end;
    size_t m_recvBuf_dataPos = 0;
    size_t m_recvLen = 0;
};

